// @cpollard
// Ω 01-03-2013 
// Punch Ticket
// auto punches your ticket and calulates time based on last 'in progress' timestamp
// EXT JS Engine already Installed - use this more over jQuery. 

function initMeOrFail() {
	try{
		punch.init();
	}catch(e){
		if(confirm('I FAILED TO RUN!!\r"'+e.message+'"\rClick Ok to open a new window and report the Error')){
			window.open('https://code.google.com/p/x-sv-js/issues/entry?template=Defect%20report%20from%20user&summary=Punch Ticket: '+e.message);
		}
	} 
}

// Punch Object
var punch = { 
	oldestTicket	: 0,
	stalestTicket	: 0,
	mostDueTicket	: 0,
	queue			: [],
	init : function(){ 
		j$ = jQuery;
		$ = temp$;

		if(j$('span[style="color: #336699;"]')){
			this.user = j$.trim(j$('span[style="color: #336699;"]').text());
		}
		
		this.jQueryPlugins();
		this.doAction();
	},

	doAction	: function(){ 
		switch(this.getUrlParams().action){
			case('ticket_dash'):
				this.colorDash();
			break;
			case('ticketdetail'):
				this.comments = j$('[name="comment"]');
				var commentPage = j$('td.smformhead:contains("Add Comment")')[0]; 
				this.commentPage(commentPage);
			break
			case('acctdetail'): 
				this.tickets = j$('[name="filterFrm"]').siblings('table')[0];
				this.colorGrid(this.tickets,7,2,9,11,3);
			break;
			default: // Index  
				this.tickets = j$('#ticketgrid_1 table table')[0];
				this.colorGrid(this.tickets,8,2,9,10,3);

			break;
		};
	}, 
	colorDash 	: function(){
		j$('tr').each(function(){
			if(this.cells.length == 12){ 
				var submit =  j$.trim(j$(this.cells[9] ).text());
				if(submit != ''){
					var now = new Date();
					var submittedOn = punch.calcDate( submit  );
					var oldness = (now-submittedOn)/(1000*60*60*24);
					punch.oldestTicket = ( parseInt(oldness) > punch.oldestTicket ) ? oldness : punch.oldestTicket;


					// Calc most due ticket. 
					var dueday = punch.calcDate(j$.trim(j$(this.cells[1]).text())); 
					var dueness 	= (now-dueday)/(1000*60*60*24); 
					punch.mostDueTicket = ( dueness > punch.mostDueTicket ) ? dueness : punch.mostDueTicket;


				}
				j$(this).toggleClass('ticketRow');
				punch.queue[j$.trim(j$(this.cells[0]).text())] = this;

			}
		});

		
		var oldest = Math.floor(punch.oldestTicket);
		var baseRed = prompt("The oldest Ticket is "+oldest+" days old.\rHow many Days for Red? (Default: 45)",oldest);

		this.iconType(j$('.ticketRow'),7);
		this.colorPriority(j$('.ticketRow'),8);

		j$.each( punch.queue, function(index,row){
			
			if(typeof row != 'undefined'){
				var cells = row.cells;
			//////alert(cells.length);
			var now = new Date();
				//////alert(cells[1].innerText.trim());
				var submittedOn = punch.calcDate(j$.trim(j$(cells[9]).text())); 
				
				var oldness 	= (now-submittedOn)/(1000*60*60*24); 
				//this.oldestTicket = ( oldness > this.oldestTicket ) ? oldness : this.oldestTicket; 
				

				val = (oldness / parseInt(baseRed)) * 100;

				////alert(punch.hsv2rgb(h,s,v));

				if (val > 100) {
					val = 100;
				}
				else if (val < 0) {
					val = 0;
				} 

				var hsv = {
					hue : Math.floor((100 - val) * 120 / 100) ,
					saturation :  Math.abs(val - 50)/50,
					value : 1

				};

				var h= Math.floor((100 - val) * 120 / 100);
				var s = Math.abs(val - 50)/50;
				var v = 1; 

				j$(cells[9]).css({
					backgroundColor: punch.hsv2rgb(h,s,v),
					textAlign : 'center',
					fontWeight : 'bold'
				});

				var dueday = punch.calcDate(j$.trim(j$(cells[1]).text())); 
				
				var dueness 	= (now-dueday)/(1000*60*60*24); 
				//this.oldestTicket = ( oldness > this.oldestTicket ) ? oldness : this.oldestTicket; 
				

				val = (dueness / parseInt( punch.mostDueTicket )) * 100;

				////alert(punch.hsv2rgb(h,s,v));

				if (val > 100) {
					val = 100;
				}
				else if (val < 0) {
					val = 0;
				} 

				h= Math.floor((100 - val) * 120 / 100);
				s = Math.abs(val - 50)/50;
				v = 1; 

				j$(cells[1]).css({
					backgroundColor: punch.hsv2rgb(h,s,v),
					textAlign : 'center',
					fontWeight : 'bold'
				});		
			}
			
		});

},
iconType 	: function(rows, cellIndex){
	var icon_cdn = 'http://famfamfam.googlecode.com/hg/silk/png/';
	j$(rows).each(function(){
		var ticketTypeEl = j$(this)[0].cells[cellIndex];
		var ticketType = j$.trim(j$(ticketTypeEl).text());
		var icon;
		switch(ticketType){
			case('Request'):
			icon = 'lightbulb';

			break;
			case('Report an Error'):
			icon = 'bug';
			break;
			case('Question'):
			icon = 'user_comment';
			break;
			case('Scope'):
			icon = 'date_magnify';
			break;
			default:
			icon = "";
			break;

		}
		if(icon){
			ticketTypeEl.innerHTML = "";
			j$('<img />', { 
				'src': icon_cdn+icon+'.png'
				, align : 'right'
					// , style	: 'position: absolute; left: -16px;'
				}).appendTo(ticketTypeEl);
			ticketTypeEl.innerHTML = ticketTypeEl.innerHTML + ticketType
		}
	});
},
colorPriority : function(rows, cellIndex){
	j$(rows).each(function(){
		var ticketTypeEl = j$(this)[0].cells[cellIndex];
		var priority = j$.trim(j$(ticketTypeEl).text()); 
		var color;
		switch(priority){
			case('Critical'):
			color = 'ticket_priority2';
			break;
			case('Urgent'):
			color = 'ticket_priority3'; 
			break;
			case('Important'):
			color = 'ticket_priority4';
			break; 
			case('Minor'):
			color = 'ticket_priority5';
			break;
			default:
			color = "";
			break; 
		}
		if(color){
			j$(ticketTypeEl).parent().addClass(color);
			j$(ticketTypeEl).parent().css({
				border : '1px solid red'
			});
			j$(ticketTypeEl).parent().children('td').addClass('priorityItem');
		}
	});
},

calcDate	: function(MDY){ 
	MDY = MDY.split('-'); 
	return  new Date(MDY[2],MDY[0]-1,MDY[1]);
},
	// This accepts a table, grid, and uses the rows to compare to the oldestday given and colors the 
	// cells from Red to Green in comparison. Red Being the Oldestday. The column is the index 
	// holds the dates
	colorDate 	: function(grid,column,oldestday){
		var now = new Date();
		for(key in grid.rows){
			if(key > 0){
				////alert(grid.rows[key].cells[1].innerText.trim());
				var day = punch.calcDate(j$(grid.rows[key].cells[column]).text().trim()); 
				
				var oldness 	= (now-day)/(1000*60*60*24); 
				//this.oldestTicket = ( oldness > this.oldestTicket ) ? oldness : this.oldestTicket; 
				val = (oldness / oldestday) * 100;

				if (val > 100) {
					val = 100;
				}
				else if (val < 0) {
					val = 0;
				} 


				var h= Math.floor((100 - val) * 120 / 100);
				var s = Math.abs(val - 50)/50;
				var v = 1;  

				
				j$(grid.rows[key].cells[column]).css({
					backgroundColor: this.hsv2rgb(h,s,v),
					textAlign : 'center',
					fontWeight : 'bold'
				});  
			}
			

		}
	}, 

	colorGrid 	: function(grid,type,priority,submitted,lastupdated,duedate){
		var now = new Date();
		for(key in grid.rows){
			if(key > 0){
				// Calc most due ticket. 
				var dueday 			= punch.calcDate(j$(grid.rows[key].cells[duedate]).text().trim()); 
				var dueness 		= (now-dueday)/(1000*60*60*24); 
				this.mostDueTicket 	= ( dueness > this.mostDueTicket ) ? dueness : this.mostDueTicket;

				// Calc oldest ticket
				var submittedOn 	= punch.calcDate(j$(grid.rows[key].cells[submitted]).text().trim());
				var oldness 		= (now-submittedOn)/(1000*60*60*24);
				this.oldestTicket 	= ( oldness > this.oldestTicket ) ? oldness : this.oldestTicket;
				
				// Calc Most Ignored 
				var lastUpdated		= punch.calcDate(j$(grid.rows[key].cells[lastupdated]).text().trim());
				var staleness 		= (now-lastUpdated)/(1000*60*60*24);
				this.stalestTicket 	= ( staleness > this.stalestTicket ) ? staleness : this.stalestTicket;
				
				// Add days together for averaging. 
				// this.stalestTicket = this.stalestTicket + staleness;
				// this.oldestTicket = oldness + this.oldestTicket;
			} 
		}

		this.colorDate(grid,submitted,this.oldestTicket );
		
		this.colorDate(grid,lastupdated,this.stalestTicket); 

		this.colorDate(grid,duedate,this.mostDueTicket); 
		

		// this.colorDueDate(grid,duedate);
		// this.colorDate(grid,submitted,(this.oldestTicket / grid.rows.length)*2);
		// this.colorDate(grid,lastupdated,(this.stalestTicket  / grid.rows.length)*2);


		this.iconType(grid.rows,type);
		this.colorPriority(grid.rows,priority); 
	},
	HSV2RGB : function(hsv) {
		var rgb=new Object();
		if (hsv.saturation==0) {
			rgb.r=rgb.g=rgb.b=Math.round(hsv.value*2.55);
		} else {
			hsv.hue/=60;
			hsv.saturation/=100;
			hsv.value/=100;
			i=Math.floor(hsv.hue);
			f=hsv.hue-i;
			p=hsv.value*(1-hsv.saturation);
			q=hsv.value*(1-hsv.saturation*f);
			t=hsv.value*(1-hsv.saturation*(1-f));
			switch(i) {
				case 0: rgb.r=hsv.value; rgb.g=t; rgb.b=p; break;
				case 1: rgb.r=q; rgb.g=hsv.value; rgb.b=p; break;
				case 2: rgb.r=p; rgb.g=hsv.value; rgb.b=t; break;
				case 3: rgb.r=p; rgb.g=q; rgb.b=hsv.value; break;
				case 4: rgb.r=t; rgb.g=p; rgb.b=hsv.value; break;
				default: rgb.r=hsv.value; rgb.g=p; rgb.b=q;
			}
			rgb.r=Math.round(rgb.r*255);
			rgb.g=Math.round(rgb.g*255);
			rgb.b=Math.round(rgb.b*255);
		}
		return rgb;
	},
	rgbToHex	: function (R,G,B) {return this.toHex(R)+this.toHex(G)+this.toHex(B)},
	toHex : function (n) {
		n = parseInt(n,10);
		if (isNaN(n)) return "00";
		n = Math.max(0,Math.min(n,255));
		return "0123456789ABCDEF".charAt((n-n%16)/16)
		+ "0123456789ABCDEF".charAt(n%16);
	},
	hsv2rgb : function(h, s, v) {
		// adapted from http://schinckel.net/2012/01/10/hsv-to-rgb-in-javascript/
		var rgb, i, data = [];
		if (s === 0) {
			rgb = [v,v,v];
		} else {
			h = h / 60;
			i = Math.floor(h);
			data = [v*(1-s), v*(1-s*(h-i)), v*(1-s*(1-(h-i)))];
			switch(i) {
				case 0:
				rgb = [v, data[2], data[0]];
				break;
				case 1:
				rgb = [data[1], v, data[0]];
				break;
				case 2:
				rgb = [data[0], v, data[2]];
				break;
				case 3:
				rgb = [data[0], data[1], v];
				break;
				case 4:
				rgb = [data[2], data[0], v];
				break;
				default:
				rgb = [v, data[0], data[1]];
				break;
			}
		}
		return '#' + rgb.mappp(function(x){
			return ("0" + Math.round(x*255).toString(16)).slice(-2);
		}).join('');
	},
	makeColor	: function (inputValue) {
	    // inputValue is a value between 0 and 511; 
	    // 0 = red, 255 = yellow, 511 = green.
	    var redValue;
	    var greenValue;
	    if (value < 255) {
	    	redValue = 255;
	    	greenValue = Math.sqrt(value) * 16;
	    	greenValue = Math.round(greenValue);
	    } else {
	    	greenValue = 255;
	    	value = value - 255
	    	redValue = 256 - (value * value / 255)
	    	redValue = Math.round(redValue);
	    }
	    var hexColor = "#" + redValue.toString(16) + greenValue.toString(16) + "00";

	    return hexColor;
	},
	commentPage : function(commentPage){
	
		//this.comments[0].scrollIntoView();

		this.newStatus = j$('[name="newstatusID"]');
		this.newUser =  j$('[name="newuserID"]');

		this.statusTrace = j$('.datalabel:contains("Pending")').parent().parent();
		if(this.statusTrace.length == 0){
			this.statusTrace = j$('.datalabel:contains("Assigned")').parent().parent();
			if(this.statusTrace.length > 1){
				this.statusTrace = j$( j$('.datalabel:contains("Assigned")').parent().parent()[1]);

			}
		}


		var cells = this.statusTrace.children('tr')[0].cells;
		var stamp = j$(cells[0]).text().trim().split(' '); // Date(year, month, day, hours, minutes, seconds, milliseconds)
		var date = stamp[0].split('-');
		var time = stamp[1].split(':');

		// consider PM 
		if(stamp[2] == "PM" && time[0] != 12){
			time[0] = 12 + Math.floor(time[0]);
		}

		this.stamp = stamp = {
			year  	: date[2],
			month 	: date[0]-1,
			day		: date[1], 
			hour 	: time[0],
			min 	: time[1]
		};

		

		this.lastPunch = {
			time 	: new Date(stamp.year,stamp.month,stamp.day,stamp.hour,stamp.min),
			status 	: j$(cells[1]).text().trim(),
			user	: j$(cells[2]).text().split(':')[1].trim()
		};

		this.getStatus(); 
		commentPage.scrollIntoView();
	},
	addComment : function(comment){
		var pre = (this.comments.val().length>0)? this.comments.val()+"\r" : ""; 
		this.comments.val(pre+comment);
	},
	/*
	Gets the status of the ticket and punches it accordingly. 
	*/
	getStatus 		: function(){
		switch(this.lastPunch.status){
			case('Assigned'):
			j$('#addtime0').attr({checked:true});
			j$('#addtime0').click();
			j$('#subscribe1').attr({checked:true});

			this.comments.css({
				width: '300px',
				height : '25px'
			});

			this.newStatus.val(3); 
 
			this.markInProgress(); 
			break;
			case('In Progress'):

			j$('#addtime1').attr({checked:true});
			j$('#addtime1').click();

			this.comments.css({
				width: '99.5%',
				height : '375px'
			});

			this.stampTime();
 
			if(confirm("Update Status to Internal Review?")){
				this.newStatus.val(4);
				this.addComment(this.templates.iReview);	 
			}else{
				this.newStatus.val(2);
				this.addComment(this.templates.Assigned);	
			}
 
			break;
			case('Internal Review'):
			// Check if we are the same user reviewing out own things.
			//////alert('Mark Assigned');
			//punch.Assigned();
			//
			this.stampTime();
			break;
			case('Pending'):

			break;
			default:
			this.stampTime();
			break;

		}

	},
	// Creates clickable links from text links and fixes other links that break with trailing periods.
	textLinks		: function(cls){
		var rows = document.getElementsByClassName(cls)
		function replaceURLWithHTMLLinks(text) {
		    var exp = /(\b(https?|ftp|file):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/ig;
		    return text.replace(exp,"<a target='_blank' style='color: blue' href='$1'>$1</a>"); 
		}

		for(i=0;i<rows.length;i++){
		        rows[i].innerHTML = replaceURLWithHTMLLinks(rows[i].innerHTML);
		}
	},

	openLinks		: function(){
		$ = j$;
		X = 'tabTickets'; 
		var e = document.createElement('script'); 
		e.setAttribute('src', 'http://goo.gl/eSb2h?'+(new Date().getTime()+'').substring(9,8)); 
		document.body.appendChild(e); 

		// look in datadesc and datafield for links and open them all in a new window together.
		// Holds The Links found in a ticket, may be usefull to grab from other functions.
		// punch.links = []; 


		// var left = (screen.width/2);
		// var top = 0; // (screen.height/2)-(h/2);

		// punch.textLinks('datafield');
		// punch.textLinks('datadesc');
		
		 

		// var prepLinks = function() {
		// 	j$(this).find('a').each(function(h,i){
		// 		var href = j$(this).attr('href'); 
		// 		punch.links.push(href)
		// 	});
		// }

		// j$('.datafield').each(prepLinks);
		// j$('.datadesc').each(prepLinks);

		// var tabs = window.open(window.location.href);
		// tabs.links = punch.links; 
	 //    tabs.onload = function() {
	 //        var doc = tabs.document;
 	//         var js = 'tabTickets'
		// 	var e = doc.createElement('script');
		// 	e.setAttribute('src', 'http://x-sv-js.googlecode.com/svn/trunk/bookmarklets/'+js+'.js?'
		// 		+(new Date().getTime()+"").substring(0,7));
		// 	doc.body.appendChild(e);
		// 	window.scrollTo(0,0);
	 //    };
	 //    tabs.onload2 = tabs.onload;
	 //    setTimeout(tabs.onload2,1500);
		// // for (var i = punch.links.length - 1; i >= 0; i--) {
		// // 	var href = punch.links[i]; 

		// // 	var where = href.substring(0,2);
		// // 	if(href.substring(0,2) != '<a'){
		// // 		var link = window.open(href);
		// // 		//link.resizeTo(1050,screen.height);
		// // 		//link.moveTo(screen.width,top); 
		// // 	}else{

		// // 	} 
		// // };


	},

	callTicketsProgress : function(){
		punch.ticketID = this.getUrlParams().ticketID;
		


		tickets.confirmStatChange = function (id, stat, ttab) {
			var _this = this;
			if (confirm('Are you sure you want to mark this Ticket as "In Progress"?')) {
				var cnt = new Ajax.Request('./act_updatestatus.cfm?ticketID=' + id + '&statusID=' + stat,
					{
						'onSuccess': function (response) {
							js_tickload.clear();
							_this.getTabCounts();
							_this.loadGrid();
							return true; 
						},
						'onFailure': function(response) { $('errmsg').innerHTML = response.responseText; return false; }
					}
				);
			}
		}(punch.ticketID, 3, 1);
		this.openLinks(); 
	},

	markInProgress : function(){
		var js = 'tickets/widget.js';
		var cdn = 'http://projects.simpleviewinc.com/dashboard/';
		var e = document.createElement('script');
		var d = new Date();
		e.setAttribute('src', cdn+js+'?'+d.getMonth());
		e.setAttribute('onload', "punch.callTicketsProgress();");	// init punch when loaded. 
		document.body.appendChild(e);

		// if(confirm("Update Status to In Progress?")){
		// 	this.newStatus.val(3); 
		// } 
		// var comment =prompt("Auto-Punching Ticket 'In Progress' w/ Following comment:",this.templates.InProgress);
		// if(comment.length > 0){

		// 	this.addComment(comment);	
		// }
	},
	stampTime 	: function(){	
		var now 	= this.timeStringToFloat(new Date());
		var then 	= this.timeStringToFloat(this.lastPunch.time); 
		this.hoursDiff(then,now);

		// Round the time.
		// 
		if(typeof this.mins != 'undefined' ){ 
			this.mins = this.mins.substring(0,2); 
		}else{
			this.mins = 00;
			this.hours = 00;
		}

		if(this.mins <= 25){
			this.mins = 15;
		}else if(this.mins <= 50){
			this.mins = 30;
		}else if(this.mins <= 75){
			this.mins = 45;
		}else{
			this.hours++;
			this.mins = 00;
		} 

		j$('#time_hrs').val(this.hours);
		j$('#time_mins').val(this.mins);

		var estimate = this.hours+'.'+this.mins;
		var time = prompt("Punching Ticket for Total Calulated Time of: "+this.hours+"hr(s) "+this.mins+"min(s)",estimate);
		
		time = (!time) ? estimate : time;

		var hour = time.split('.')[0];
		var min = time.split('.')[1];
		// Decimal conversion 
		min = min == 75 ? 45 : min == 7 ? 45 : min == 50 ? 30 : min == 5 ? 30 : min == 25 ? 15 : min == 2 ? 15 : min;

		j$('#time_hrs').val(hour);
		j$('#time_mins').val(min);

		// Create Ticket cookie
		this.cookie = {
			id : this.getUrlParams().ticketID,
			hours : j$.cookie("punch_hours")+hour,
			mins : j$.cookie("punch_mins")+min
		};

		var expire = new Date();
		expire.setYear(expire.getYear()+2);	// 5 Year cookie. 

		j$.cookie("punch_ticket_id",this.cookie.id, { 	expires: expire });
		j$.cookie("punch_hours_"+this.cookie,this.cookie.hours, { 	expires: expire });
		j$.cookie("punch_mins_"+this.cookie,this.cookie.mins, { 		expires: expire });
	},

	timeStringToFloat	: function (time) {
		var hoursMinutes = [time.getHours(),time.getMinutes()];
		var hours = parseInt(hoursMinutes[0], 10);
		var minutes = hoursMinutes[1] ? parseInt(hoursMinutes[1], 10) : 0;
		return hours + minutes / 60;
	},

	hoursDiff	: function (t1, t2){ 
		this.time 	= "" + (t2-t1); 
		this.hours 	= this.time.split('.')[0];
		this.mins 	= this.time.split('.')[1]; 

		// Parse out the times, using radix 10 to
		// avoid octal edge cases ("08:00" & "09:00")
		var time1   = parseInt( t1, 10 );
		var time2   = parseInt( t2, 10 );
		var hours   = 0;

		while ( time1 !== time2 ){
			time1++;
			hours++;

		  // If we've passed midnight, reset
		  // to 01:00AM
		  if ( time1 === 25 ){
		  	time1 = 1;
		  }  
		} 
		return hours;
	},
	templates : {
		InProgress 	: "In Progress",
		Assigned	: "",
		cReview		: "",
		iReview 	: "ToWhomItMayConcern,\r"
		+"The above has been addressed.\r\r"
		+"=== TESTED ON: [] ===\r\r"
		+"== r&d ==\r\r"
		+"== links ==\r\r"
		+"== screenshots ==\r\r"
		+"== files updated ==\r\r"
		+"== dev notes ==\r\r"
	},
	// PUNCH TICKET COOKIE
	// Keep's track of ticket numbers you've punched including TIME
	// ON the index of the tiket queue, it will ////alert you of tickets that come back to you, in order of how much time YOUVE ADDED
	//
	getUrlParams	: function() {
		var params = {};
		window.location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi, function(str,key,value) {
			params[key] = value;
		});

		return params;
	}, 
	jQueryPlugins	: function(){
		/*!
		 * jQuery Cookie Plugin v1.3
		 * https://github.com/carhartl/jquery-cookie
		 */
		 (function ($, document, undefined) {

		 	var pluses = /\+/g;

		 	function raw(s) {
		 		return s;
		 	}

		 	function decoded(s) {
		 		return decodeURIComponent(s.replace(pluses, ' '));
		 	}

		 	var config = $.cookie = function (key, value, options) {

				// write
				if (value !== undefined) {
					options = $.extend({}, config.defaults, options);

					if (value === null) {
						options.expires = -1;
					}

					if (typeof options.expires === 'number') {
						var days = options.expires, t = options.expires = new Date();
						t.setDate(t.getDate() + days);
					}

					value = config.json ? JSON.stringify(value) : String(value);

					return (document.cookie = [
						encodeURIComponent(key), '=', config.raw ? value : encodeURIComponent(value),
						options.expires ? '; expires=' + options.expires.toUTCString() : '', // use expires attribute, max-age is not supported by IE
						options.path    ? '; path=' + options.path : '',
						options.domain  ? '; domain=' + options.domain : '',
						options.secure  ? '; secure' : ''
						].join(''));
				}

				// read
				var decode = config.raw ? raw : decoded;
				var cookies = document.cookie.split('; ');
				for (var i = 0, l = cookies.length; i < l; i++) {
					var parts = cookies[i].split('=');
					if (decode(parts.shift()) === key) {
						var cookie = decode(parts.join('='));
						return config.json ? JSON.parse(cookie) : cookie;
					}
				}

				return null;
			};

			config.defaults = {};

			$.removeCookie = function (key, options) {
				if ($.cookie(key) !== null) {
					$.cookie(key, null, options);
					return true;
				}
				return false;
			};

		})(jQuery, document);
	}
};

if (!Array.prototype.mappp) {
	Array.prototype.mappp = function(fun /*, thisp*/) {
		var len = this.length >>> 0;
		if (typeof fun != "function") {
			throw new TypeError();
		}

		var res = new Array(len);
		var thisp = arguments[1];
		for (var i = 0; i < len; i++) {
			if (i in this) {
				res[i] = fun.call(thisp, this[i], i, this);
			}
		}

		return res;
	};
}


if(typeof jQuery == 'undefined'){
	// Install jQuery.
	var temp$ = $;				
	var js = '1.8/jquery.min.js';
	var cdn = 'http://ajax.googleapis.com/ajax/libs/jquery/';
	var e = document.createElement('script');
	var d = new Date();
	e.setAttribute('src', cdn+js+'?'+d.getMonth());
	e.setAttribute('onload', "initMeOrFail();");	// init punch when loaded. 
	document.body.appendChild(e);	
}else{
	initMeOrFail();
}
